#
# "@(#) $Id: LibraryView.py,v 1.1.1.1 2006-07-27 03:16:08 gioshe Exp $"
#
# This work is released under the GNU GPL, version 2 or later.
#
from Utils.kdeemul import *
from DB.Library import *
from LibraryViewItem import *
from TrackDrag import *
from TrackView import *
from Utils.Settings import *
from MultipleDrag import *
from RemoteTrackDrag import *
from RemotePlaylistDrag import *
import random
from Utils.utils import *
#import traceback

def removeDuplicates(items):
	result = {}
	for item in items:
		result[item] = 1
	return result.keys()

def cleanup(fileList):
	#print "cleanup",fileList
	files = []
	for file in fileList:
		files.append(unikode(file).encode('ISO-8859-1'))
	return files

class LibraryView(TrackView,KListView):
	def __init__(self,container,name='library'):
		TrackView.__init__(self)
		KListView.__init__(self,container,name)
		self.settings = Settings.settings()
		self.bulkEdit = False
		self.library = Library.mainLibrary()
		self.setCurrentPlaylist()
		self.setSelectionMode(QListView.Extended)
		self.setAllColumnsShowFocus(True)
		self.headers=[False,False,False,False,False,False,False,False]
		self.loadHeaders()
		c = QColor(237,243,254)
		self.setAlternateBackground(c)
		try: self.setShareSortColumn(True) # if KDE 3.4
		except: pass
##~ 		self.searchType = 'all'
##~ 		self.searchText = ''
		self.currentArtists = None
		self.currentAlbums = None
##~ 		self.loadArtistsAndAlbums()
		self.setAcceptDrops(True)
		self.setDropHighlighter(True)
		self.setDropVisualizer(False)
		if(self.settings.get("Show Rating")) or name!='library':
			#print "connecting the ratewidgsignal", name
			QObject.connect(self,SIGNAL("clicked(QListViewItem *, const QPoint &, int)"),self.clickedItemColumnPoint)
		QObject.connect(self,SIGNAL("selectionChanged()"),self.doSelectionChanged)
		QObject.connect(self,SIGNAL("contextMenuRequested(QListViewItem *, const QPoint &, int)"),self.contextMenu)
		#QObject.connect(self,PYSIGNAL("addedTracks"),self.addedTracks)
		#QObject.connect(self,PYSIGNAL("bulkEditEnd"),self.bulkEditEnd)
		self.loadTracks()

	def bulkEditBegin(self):
		print "BULK BEGIN<<<"
		self.bulkEdit = True
	
	def bulkEditEnd(self):
		self.bulkEdit = False
		self.loadTracks()

	def setCurrentPlaylist(self):
		self.playlistName = "Library"
		self.playlist = self.library.playlistWithName(self.playlistName)
		self.library.connect(PYSIGNAL("addedTracks"),self.addedTracks)
		self.playlist.connect(PYSIGNAL("removedTrack"),self.removedTrack)
	
	def loadHeaders(self):
		headers=[' ']
		widths=[40]
		print self.playlistName, "PLS NAME"
		if self.playlistName=='Library':
			print "inside the loop"
			if(self.settings.get("Show Title")):
				headers.append(i18n("Song Name"))
				widths.append(220)
				self.headers[0]=1
				print "adding stuff ",headers,widths
			if(self.settings.get("Show Time")):
				headers.append(i18n("Time"))
				widths.append(40)
				self.headers[1]=2
			if(self.settings.get("Show Artist")):
				headers.append(i18n("Artist"))
				widths.append(120)
				self.headers[2]=3
			if(self.settings.get("Show Album")):
				headers.append(i18n("Album"))
				widths.append(180)
				self.headers[3]=4
			if(self.settings.get("Show Genre")):
				headers.append(i18n("Genre"))
				widths.append(80)
				self.headers[4]=5
			if(self.settings.get("Show Rating")):
				headers.append(i18n("My Rating"))
				widths.append(80)
				self.headers[5]=6
			if(self.settings.get("Show Count")):
				headers.append(i18n("Play Count"))
				widths.append(70)
				self.headers[6]=7
			if(self.settings.get("Show Last Played")):
				headers.append(i18n("Last Played"))
				widths.append(130)
				self.headers[7]=8
		else:
##			pass
##		print headers," HEADERS WIDTHS ",widths
##		headers=[" "]	
##		widths=[40]
			self.headers=[1,2,3,4,5,6,7,8]
			headers.extend([i18n("Song Name"),i18n("Time"),i18n("Artist"),i18n("Album"),i18n("Genre"),i18n("My Rating"),i18n("Play Count"),i18n("Last Played")])
			widths.extend([220,40,120,180,80,80,70,130])
		for index in xrange(0,len(headers)):
			if headers[index]:
				self.addColumn(headers[index],widths[index])
				#print headers[index], " header <<<>>>width ",widths[index]
				if headers[index]==(i18n("My Rating")):
					self.ratingColumn = index
		self.setShowSortIndicator(True)
		#self.setFullWidth(True)
		self.setColumnAlignment(7,Qt.AlignCenter)
		
		#GTD possible problem here with the columns 
		#FIX ME : if sorting is on a column that is not in 
		# the current range we have to handle it by defaulting to the smallest we have
		sortColumn = self.settings.get('Main Library Sort Column',3)
		sortAscending = self.settings.get('Main Library Sort Ascending',True)
		self.setSorting(sortColumn,sortAscending)
		QObject.connect(self.header(),SIGNAL("indexChange(int,int,int)"),self.columnIndexChanged)
		QObject.connect(self.header(),SIGNAL("sizeChange(int,int,int)"),self.columnSizeChanged)
		self.loadHeaderSizes('Main Library Header Widths')
		self.loadHeaderOrdering('Main Library Header Map')

	def loadPlaylist(self,playlistName):
		playlist = self.library.playlistWithName(playlistName)
		self.setPlaylist(playlist)

	def loadTrackItem(self,track):
		item = LibraryViewItem(self,track,self.headers)
		


	def loadArtistsAndAlbums(self,artists=None,albums=None):
		self.currentArtists = artists
		if artists:
			self.currentArtists = map(lambda artist:artist.upper(),artists)
		self.currentAlbums = albums
		if albums:
			self.currentAlbums = map(lambda album:album.upper(),albums)
		self.loadTracks()

	def trackMatches(self,track):
#~ 		if self.currentArtists!=None:
##~ 			for artist in self.currentArtists:
##~ 				print type(artist)
		artist = None
		album = None
		if track.artist!=None: artist = unikode(track.artist)
		if track.album!=None: album = unikode(track.album)
		if self.currentArtists==None or len(self.currentArtists)==0 or (artist!=None and artist.upper() in self.currentArtists):
			if self.currentAlbums==None or len(self.currentAlbums)==0 or (album!=None and album.upper() in self.currentAlbums):
				if self.matchesSearch(track):
						return True
		return False
	
	def addedTracks(self):
		print "GOT THE SIGNAL:"
		#if False: #not self.bulkEdit:
		#	track = self.library.trackWithTrackID(trackID)
		#	if self.trackMatches(track):
		#		self.loadTrackItem(track)
		#self.emitCurrentEnabledSortedTracks()
		self.loadTracks()
		#	print "CHANGED"
		self.emit(PYSIGNAL("changed"),(self,None))

	def removedTrack(self,library,trackID):
		#print "LibraryView removed track",trackID
		if not self.bulkEdit:
			track = library.trackWithTrackID(trackID)
			item = self.firstChild()
			while item:
				if item.track()==track:
					self.takeItem(item)
					del item
					break
				item = item.itemBelow()
			self.emitCurrentEnabledSortedTracks()
			self.emit(PYSIGNAL("changed"),(self,None))
		
	def loadTracks(self):
		#import traceback
		#traceback.print_stack()
		print "loading tracks for",self.currentArtists,self.currentAlbums
		playlist = self.library.playlistWithName("Library")
		tracks = playlist.tracks
		items = []
		for track in tracks:
			if track and self.trackMatches(track):
				items.append(track)
		sortColumn = self.settings.get('Main Library Sort Column',3)
		sortAscending = self.settings.get('Main Library Sort Ascending',True)
		#print "loading tracks in library"
		self.clear()
		self.setUpdatesEnabled(False)
		self.blockSignals(True)
		self.setSorting(-1,True)
		for track in items:
			if track: self.loadTrackItem(track)
		self.setSorting(sortColumn,sortAscending)
		self.blockSignals(False)
		self.setUpdatesEnabled(True)
		self.update()
		self.emit(PYSIGNAL("changed"),(self,None))

	def refresh(self):
		self.loadArtistsAndAlbums(self.currentArtists,self.currentAlbums)

	def printFormats(self,event):
		print("formats:")
		n = 0
		while True:
			format = event.format(n)
			if (format==None):
				break
			print("  "+str(format))
			n = n+1
	
	def contentsMouseDoubleClickEvent(self,event):
		pos = self.contentsToViewport(event.pos())
		item = self.itemAt(pos)
		if item:
			item.contentsMouseDoubleClickEvent(event)

	#
	# drop methods used by Qt
	#
	def contentsDragEnterEvent(self,event):
		if QUriDrag.canDecode(event):
			uris = QStringList()
			if QUriDrag.decodeLocalFiles(event,uris):
				uris = cleanup(uris)
				if self.library.canImportFiles(uris):
					event.accept(True)

	def contentsDropEvent(self,event):
		if RemoteTrackDrag.canDecode(event):
			print "dropped remote drag on library"
			return
		uris = QStringList()
		if QUriDrag.decodeLocalFiles(event,uris):
			uris = cleanup(uris)
			self.library.importFiles(removeDuplicates(uris),None)

	#
	# drop methods used by KDE
	#	
	def acceptDrag(self,event):
		if RemoteTrackDrag.canDecode(event): return True
		if QUriDrag.canDecode(event): return True
			# XXX DSM removed due to Qt bug
##~ 			uris = QStringList()
##~ 			if QUriDrag.decodeLocalFiles(event,uris):
##~ 				uris = cleanup(uris)
##~ 				if self.library.canImportFiles(uris):
##~ 					return True
		return False
	
	def anyItemsSelected(self):
		item = self.firstChild()
		while item:
			if item.isSelected():
				return True
			item = item.itemBelow()
		return False

	def selectedTrackIDs(self):
		result = []
		item = self.firstChild()
		while item:
			if item.isSelected():
				result.append(item.trackID())
			item = item.itemBelow()
		return result

	def selectedTracks(self):
		result = []
		item = self.firstChild()
		while item:
			if item.isSelected():
				result.append(item.track())
			item = item.itemBelow()
		return result

	def selectedItems(self):
		result = []
		item = self.firstChild()
		while item:
			if item.isSelected():
				result.append(item)
			item = item.itemBelow()
		return result
	
	def firstSelectedItem(self):
		items = self.selectedItems()
		if len(items)>0:
			return items[0]
		return None

	def selectAll(self,select):
		KListView.selectAll(self,select)
##~ 		item = self.firstChild()
##~ 		while item:
##~ 			if item.isSelected()!=select:
##~ 				self.setSelected(item,select)
##~ 			item = item.itemBelow()
##~ 		#self.repaint()

	def removeSelectedItems(self):
		trackIDs = self.selectedTrackIDs()
		self.playlist.removeTrackIDs(trackIDs)
		trash = self.library.playlistWithName('Trash')
		if trash:
			trash.addTrackIDs(trackIDs)
	
	def dragObject(self):
		#print "dragging object"
		selectedTracks = self.selectedTrackIDs()
		tracks = self.library.tracksWithTrackIDs(selectedTracks)
		locations = [track.location for track in tracks]
		drag = MultipleDrag(self)
		self.tdrag = TrackDrag(selectedTracks,self.playlist,None)
		drag.addDragObject(self.tdrag)
		self.udrag = QUriDrag(locations)
		drag.addDragObject(self.udrag)
#		drag = TrackDrag(selectedTracks,self.playlist,self)
		drag.dragCopy()

	def copySelectionToPlaylist(self,playlist):
		items = self.selectedTrackIDs()
		playlist.addTrackIDs(items)

	def setSearchType(self,searchType):
		self.searchType = searchType
		self.loadTracks()

	def setSearchText(self,searchText):
		self.searchText = searchText
		print "Searching for ",searchText
		self.loadTracks()

	def xrandomItem(self):
		count = self.childCount()
		r = random.Random()
		index = r.randint(0,count-1)
		item = self.firstChild()
		while item and index:
			item = item.itemBelow()
			index = index-1
		return item

	def xtrackItemToPlay(self):
		items = self.selectedItems()
		if len(items)==0:
			# XXX DSM exclude items checked off
			items = [self.randomItem()]
		return items[0]

	def play(self):
		item = self.firstSelectedItem()
		if item:
			#print "playing selected item"
			item.track().play(self.playlist)
		else:
			#print "playing some item"
			Player.playItemFrom(self.library,self.playlist)
	
	def clickedItemColumnPoint(self,item,point,column):
		if item and column==self.ratingColumn:
			r = self.itemRect(item)
			point = self.mapFromGlobal(point)
			px = point.x()
			px = px-self.header().sectionPos(column)-3 # XXX DSM fudge out width of frame??
			point = self.viewportToContents(QPoint(px,point.y()))
			px = point.x()
			#print "clicked",item,"column",column,"at",px
			item.clickedRatingAt(px)

	def setSorting(self,column,ascending = True):
		KListView.setSorting(self,column,ascending)
		self.settings['Main Library Sort Column'] = column
		self.settings['Main Library Sort Ascending'] = not not ascending
		self.emitCurrentEnabledSortedTracks()

	def doSelectionChanged(self):
		if self.anyItemsSelected():
			Player.selectedTrack()
	
	def clear(self):
		item = self.firstChild()
		while item:
			item.die()
			item = item.itemBelow()
		KListView.clear(self)
	
	def columnIndexChanged(self,section,fromIndex,toIndex):
		self.saveHeaderOrdering('Main Library Header Map')
	
	def columnSizeChanged(self,section,oldSize,newSize):
		self.saveHeaderSizes('Main Library Header Widths')

	def contextMenu(self,item,pos,col):
		if item:
			item.contextMenu(pos,col)

	def createArtistPlaylist(self,artist):
		trackIDs = self.library.playlistWithName('Library').trackIDsForArtists([artist])
		self.library.addPlaylistFromTrackIDs(trackIDs)
	
	def createAlbumPlaylist(self,album):
		trackIDs = self.library.playlistWithName('Library').trackIDsForAlbums([album])
		self.library.addPlaylistFromTrackIDs(trackIDs)
	
	def canShowCurrent(self):
		return True

	def rename(self,item,column):
		KListView.rename(self,item,column)
		#print "about to rename",item,column
		completion = self.renameLineEdit().completionObject()
		completion.clear()
		if column==item.artistColumn:
			#print "setting artist completion"
			for artist in self.library.artists():
				completion.addItem(artist)
		elif column==item.albumColumn:
			#print "setting album completion"
			for album in self.library.albums():
				completion.addItem(album)
